﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace BadHabit.WPFTools {

    /// <summary>
    /// A shaped window is a transparent window that should have its content, title bar and border drawed.
    /// You should provide the following element names at the XAML: TitleBar, MaximizeButton, MinimizeButton and CloseButton.
    /// </summary>
    public class ShapedWindow : Window {

        // used to emulate the maximize
        private double oldHeight;
        private double oldWidth;
        private double oldLeft;
        private double oldTop;

        private UIElement titleBar;
        private UIElement maximizeButton;
        private UIElement minimizeButton;
        private UIElement closeButton;

       
        
        /// <summary>
        /// Constructor.
        /// </summary>
        public ShapedWindow() : base() {            
            Background = Brushes.Transparent;
            AllowsTransparency = true;
           
            Loaded += new RoutedEventHandler(ShapedWindow_Loaded);
        
        }


        public static void ShowAsSingle<T>(ref T w) where T: ShapedWindow, new() {            
            if (w == null || w.IsVisible == false) {
                w = new T();
                w.ShowDialog();                
            }
            else
                w.BringIntoView();
        }

        /// <summary>
        /// Links all the events to the window elements.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void ShapedWindow_Loaded(object sender, RoutedEventArgs e) {
            titleBar = this.Template.FindName("PART_TitleBar", this) as UIElement;
            if (titleBar != null)
                titleBar.MouseLeftButtonDown += new MouseButtonEventHandler(titleBar_MouseLeftButtonDown);


            maximizeButton = this.Template.FindName("PART_MaximizeButton", this) as UIElement;
            if (maximizeButton != null)
                maximizeButton.MouseLeftButtonDown += new MouseButtonEventHandler(maximizeButton_MouseLeftButtonDown);

            minimizeButton = this.Template.FindName("PART_MinimizeButton", this) as UIElement;
            if (minimizeButton != null)
                minimizeButton.MouseLeftButtonDown += new MouseButtonEventHandler(minimizeButton_MouseLeftButtonDown);


            closeButton = this.Template.FindName("PART_CloseButton", this) as FrameworkElement;
            if (closeButton != null) {
                if (closeButton is Button) {
                    Button closeButtonB = closeButton as Button;
                    closeButtonB.Click += new RoutedEventHandler(closeButtonB_Click);
                } else {
                    closeButton.MouseLeftButtonDown += new MouseButtonEventHandler(closeButton_MouseLeftButtonDown);
                }
            }    
        }

        void closeButtonB_Click(object sender, RoutedEventArgs e) {
            Close();
        }

        /// <summary>
        /// Closes the window.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void closeButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
            Close();
        }

        /// <summary>
        /// When the minimize button is clicked, minimizes it.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void minimizeButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {            
            WindowState = WindowState.Minimized;            
        }

        /// <summary>
        /// When the maximize button is clicked expands the window.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void maximizeButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
            IsMaximized = !IsMaximized;
        }

        /// <summary>
        /// When the title bar is clicked, change its states ou drags it.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void titleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
            OnTitleBarMouseLeftDown(e);
        }

        /// <summary>
        /// Gets and Sets whenever the window is maximized.
        /// When using a tranparent window, the maximized state overlaps the
        /// task bar. This fix this ugly behaviour.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public bool IsMaximized {
            get {
                return (Width == System.Windows.SystemParameters.PrimaryScreenWidth && Height == System.Windows.SystemParameters.WorkArea.Height);
            }
            set {
                if (ResizeMode == ResizeMode.NoResize)
                    return;
                WindowState = WindowState.Normal;
                if(value) {
                    oldTop = Top;
                    oldLeft = Left;
                    oldHeight = ActualHeight;
                    oldWidth = ActualWidth;
                    Left = 0;
                    Top = 0;
                    Width = System.Windows.SystemParameters.PrimaryScreenWidth;
                    Height = System.Windows.SystemParameters.WorkArea.Height;
                }
                else {
                    Top = oldTop;
                    Left = oldLeft;
                    Width = oldWidth;
                    Height = oldHeight;
                }
            }
        }

        /// <summary>
        /// If was a drag, drag it, otherwize changes it states.
        /// </summary>
        /// <param name="e"></param>
        protected void OnTitleBarMouseLeftDown(MouseButtonEventArgs e) {
            if (e.ClickCount >= 2)
                IsMaximized = !IsMaximized;
            else {                        
                this.DragMove();
            }
        }
        
    }
}
